package paystation.view;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.util.Date;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.UIManager;

import paystation.domain.IllegalCoinException;
import paystation.domain.PayStation;
import paystation.domain.PayStationImpl;
import paystation.domain.Receipt;
import softcollection.lcd.LCDDigitDisplay;

/**
 * A graphical user interface used as alternative to a real hardware to operate the PayStation domain code.
 */
public class PayStationGUI extends JFrame {

    /**
	 * 
	 */
	private static final long serialVersionUID = -6535704405549155769L;

	public static void main(String[] args) throws RemoteException, MalformedURLException {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            // ignore silently, as we then just do not get the required
            // look and feel for all windows
        }
		String host = "localhost";
		if (args.length > 0) {
			host = args[0];
		}

		if (System.getSecurityManager() == null) {
			System.setSecurityManager(new RMISecurityManager());
		}
		
		//Torbens test
		Date date=new Date();  
				
		System.out.println("Starting Remote PayStation");
		PayStation payStationServer = new PayStationImpl();
		
		//ex of name could be : PayStation1386779321363
		Naming.rebind("//" + host + "/PayStation" + date.getTime(), payStationServer);
        new PayStationGUI(payStationServer);
    }

    /** The "digital display" where readings are shown */
    LCDDigitDisplay display;
    /** The domain pay station that the gui interacts with */
    PayStation payStation;

    /** Create the GUI 
     * @throws MalformedURLException 
     * @throws RemoteException */
    public PayStationGUI(PayStation payStation) throws RemoteException, MalformedURLException {
        this(100, 20);
        this.payStation = payStation;
    }

    /** Create the GUI at (x,y) position 
     * @throws MalformedURLException 
     */
    public PayStationGUI(int x, int y) throws RemoteException, MalformedURLException {
        super("PayStation GUI");

        
        // all the gui setup
        JFrame.setDefaultLookAndFeelDecorated(true);
        setLocation(x, y);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container cpane = getContentPane();

        cpane.setLayout(new BorderLayout());

        cpane.add(createCoinInputPanel(), BorderLayout.EAST);
        cpane.add(createButtonPanel(), BorderLayout.SOUTH);

        cpane.add(createDisplayPanel(), BorderLayout.CENTER);

        display.set("   0");

        pack();
        setVisible(true);
    }

    /**
     * Update the digital display with whatever the pay station domain shows
     * @throws RemoteException 
     */
    private void updateDisplay() throws RemoteException {
        String prefixedZeros = String.format("%4d", payStation.readDisplay());
        display.set(prefixedZeros);
    }

    /** Create the coin input panel */
    private JComponent createCoinInputPanel() {
        Box p = new Box(BoxLayout.Y_AXIS);
        p.add(defineButton(" 5 c", "5"));
        p.add(defineButton("10 c", "10"));
        p.add(defineButton("25 c", "25"));
        return p;
    }

    /**
     * The button action listener that reacts on clicking the coin buttons
     */
    private ActionListener buttonActionListener = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            String s = e.getActionCommand();
            int coin = Integer.parseInt(s);
            try {
                payStation.addPayment(coin);
            updateDisplay();
            } catch (IllegalCoinException exc) {
                // illegal coins just do nothing.
            }
            catch (RemoteException excRemote)
            {
            	excRemote.printStackTrace();
            }
        }
    };

    /** Define a button's text and action command */
    private JButton defineButton(String text, String actioncommand) {
        JButton b;
        b = new JButton(text);
        b.setAlignmentX(Component.CENTER_ALIGNMENT);
        b.setActionCommand(actioncommand);
        b.addActionListener(buttonActionListener);
        return b;
    }

    /** Create the panel of buttons */
    private JComponent createButtonPanel() {
        Box p = new Box(BoxLayout.X_AXIS);
        JButton b;
        b = new JButton("Cancel");
        b.setAlignmentX(Component.CENTER_ALIGNMENT);
        p.add(Box.createHorizontalGlue());
        p.add(b);
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
					payStation.cancel();
                updateDisplay();
				} catch (RemoteException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
            }
        });

        b = new JButton("Buy");
        b.setAlignmentX(Component.CENTER_ALIGNMENT);
        p.add(Box.createHorizontalGlue());
        p.add(b);
        p.add(Box.createHorizontalGlue());
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Receipt r;
				try {
					r = payStation.buy();
                updateDisplay();
                // print the receipt
                showReceiptInWindow(r);
				} catch (RemoteException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
            }
        });

        return p;
    }

    /** Create the panel for the display */
    private JComponent createDisplayPanel() {
        display = new LCDDigitDisplay();
        return display;
    }

    private void showReceiptInWindow(Receipt receipt) {
        // make the window in which to display receipt
        JFrame frame = new JFrame("Receipt");
        // print the receipt's contents in a string array
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(baos);
        receipt.print(ps);
        String[] lines = baos.toString().split("\n");
        // copy the contents into a text area
        JTextArea text = new JTextArea(lines.length, 20);
        text.setEditable(false);
        text.setFont(new Font("DialogInput", Font.PLAIN, 14));

        for (int i = 0; i < lines.length; i++) {
            text.append(lines[i] + "\n");
        }
        frame.getContentPane().add(text);
        frame.pack();
        frame.setVisible(true);
    }

    /** return the paystation domain object */
    public PayStation getPayStation() {
        return payStation;
    }
}
